/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package wf.units;

import bc.ds.Range;
import bc.dsl.SwingDSL;
import bc.swing.pfrm.Model;
import bc.swing.pfrm.ano.Action;
import bc.swing.pfrm.ano.PageDef;
import bc.swing.pfrm.ano.Param;
import bc.swing.pfrm.layouts.FormLayout;
import bc.swing.pfrm.viewtypes.ParamType;
import bc.utils.CalendarUtils.WeekDays;
import bc.utils.SHA1Calc;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import wf.model.Counter;
import wf.model.PLC;
import wf.model.Schedule;
import wf.model.User;
import wf.model.Valve;
import wf.ui.ScheduleCreatorModifier;
import wf.ui.windows.Dialog;

/**
 *
 * @author bennyl
 */
public enum ModificationUnit {

    UNIT;

    public static void main(String[] args) {
        SwingDSL.configureUI();
        DatabaseUnit.UNIT.connect();
        UNIT.invokeScheduleCreation(new Date());
    }
    
    public boolean invokeDeletion(Object data){
        if (SwingDSL.ynqbox("Are You sure?", "are you sure you want to delete this item?")){
            DatabaseUnit.UNIT.deleteItem(data);
            return true;
        }
        return false;
    }

    public void invokeScheduleCreation(Date forDate) {
        ScheduleCreatorModifier temp = new ScheduleCreatorModifier();
        Calendar c = Calendar.getInstance();
        Calendar e = Calendar.getInstance();

        Dialog.show(temp, 500, 350);
        if (temp.isAccepted()) {
            e = temp.getEndDate();
            final int p = (int) temp.getPeriodMinute().getValue();
            final int v = temp.getValveId();

            switch (temp.getRecurrence()) {
                case None:
                    DatabaseUnit.UNIT.insertOrUpdate(new Schedule(temp.getValveId(), temp.getDayTime().getTime(), (int) temp.getPeriodMinute().getValue()));
                    break;
                case Dayly:
                    c.setTime(temp.getDayTime().getTime());
                    while (c.before(e)) {
                        DatabaseUnit.UNIT.insertOrUpdate(new Schedule(v, c.getTime(), p));
                        c.add(Calendar.DATE, (int) ((ScheduleCreatorModifier.DayRecurrence) temp.getRecurrenceData()).days.getValue());
                    }

                    break;
                case Weekly:
                    c.setTime(temp.getDayTime().getTime());
                    int w = 0;
                    ScheduleCreatorModifier.WeeklyRecurrence wrec = (ScheduleCreatorModifier.WeeklyRecurrence) temp.getRecurrenceData();
                    while (c.before(e)) {
                        WeekDays dow = WeekDays.byNumber(c.get(Calendar.DAY_OF_WEEK));
                        if (wrec.selectedDays.contains(dow) && w % (int) wrec.weeks.getValue() == 0) {
                            DatabaseUnit.UNIT.insertOrUpdate(new Schedule(v, c.getTime(), p));
                        }

                        c.add(Calendar.DATE, 1);
                        dow = WeekDays.byNumber(c.get(Calendar.DAY_OF_WEEK));
                        if (dow == WeekDays.Friday) {
                            w++;
                        }

                    }

                    break;
                case Monthly:
                    c.setTime(temp.getDayTime().getTime());
                    int m = 0;
                    ScheduleCreatorModifier.MonthlyRecurrence mrec = (ScheduleCreatorModifier.MonthlyRecurrence) temp.getRecurrenceData();
                    while (c.before(e)) {
                        if (c.get(Calendar.DAY_OF_MONTH) == mrec.day.getValue() && m % (int) mrec.months.getValue() == 0) {
                            DatabaseUnit.UNIT.insertOrUpdate(new Schedule(v, c.getTime(), p));
                        }

                        int pre = c.get(Calendar.MONTH);
                        c.add(Calendar.DATE, 1);
                        if (pre != c.get(Calendar.MONTH)) {
                            m++;
                        }
                    }

                    break;

            }
        }
    }

    public boolean invokeUserModification(User user) {
        final UserCreatorModifier u = new UserCreatorModifier(user);
        Dialog.show(u, 400, 150);
        if (u.getUser() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getUser());
        }
        return u.getUser() != null;
    }

    public boolean invokePLCModification(PLC plc) {
        final PLCCreatorModifier u = new PLCCreatorModifier(plc);
        Dialog.show(u, 420, 150);
        if (u.getPLC() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getPLC());
        }
        return u.getPLC() != null;
    }

    public boolean invokeValveModification(Valve v) {
        final ValveCreatorModifier u = new ValveCreatorModifier(v);
        Dialog.show(u, 420, 150);
        if (u.getValve() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getValve());
        }
        return u.getValve() != null;
    }

    public boolean invokeCounterModification(Counter c) {
        final CounterCreatorModifier u = new CounterCreatorModifier(c);
        Dialog.show(u, 480, 180);
        if (u.getCounter() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getCounter());
        }
        return u.getCounter() != null;
    }

    public User invokeUserCreation() {
        final UserCreatorModifier u = new UserCreatorModifier();
        Dialog.show(u, 400, 150);
        if (u.getUser() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getUser());
        }
        return u.getUser();
    }

    public PLC invokePLCCreation() {
        final PLCCreatorModifier u = new PLCCreatorModifier();
        Dialog.show(u, 420, 150);
        if (u.getPLC() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getPLC());
        }
        return u.getPLC();
    }

    public Valve invokeValveCreation() {
        final ValveCreatorModifier u = new ValveCreatorModifier();
        Dialog.show(u, 420, 150);
        if (u.getValve() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getValve());
        }
        return u.getValve();
    }

    public Counter invokeCounterCreation() {
        final CounterCreatorModifier u = new CounterCreatorModifier();
        Dialog.show(u, 480, 180);
        if (u.getCounter() != null) {
            DatabaseUnit.UNIT.insertOrUpdate(u.getCounter());
        }
        return u.getCounter();
    }

    @PageDef(name = "Create/Modify User", icon = "create-modify-user64", layout = FormLayout.class)
    public static class UserCreatorModifier extends Model {

        User x;
        String password;

        public UserCreatorModifier() {
            x = new User();
            password = "";
        }

        public UserCreatorModifier(User x) {
            this.x = x;
            this.password = "";
        }

        @Param(name = "Name", type = ParamType.STRING)
        public String getName() {
            return x.getName();
        }

        public void setName(String name) {
            x.setName(name);
        }

        @Param(name = "Password", type = ParamType.PASSWORD)
        public String getPassword() {
            return password;
        }

        public void setPassword(String pass) {
            this.password = pass;
            x.setPassHash(SHA1Calc.calc(pass));
        }

        @Param(name = "Role", type = ParamType.OPTIONS)
        public User.Role getRole() {
            if (x.getRole() == User.Role.ADMIN.getNum()) {
                return User.Role.ADMIN;
            } else {
                return User.Role.USER;
            }
        }

        public void setRole(User.Role role) {
            x.setRole(role.getNum());
        }

        @Action(name = Dialog.OK_ACTION)
        public void handleOK() {
            syncFromView();
            getPage().disposeView();
        }

        @Action(name = Dialog.CANCEL_ACTION)
        public void handleCANCEL() {
            x = null;
            getPage().disposeView();
        }

        public User getUser() {
            return x;
        }
    }

    @PageDef(name = "Create/Modify PLC", icon = "plc64", layout = FormLayout.class)
    public static class PLCCreatorModifier extends Model {

        PLC x;

        public PLCCreatorModifier(PLC x) {
            this.x = x;
        }

        public PLCCreatorModifier() {
            x = new PLC();
        }

        @Param(name = "Name", type = ParamType.STRING)
        public String getName() {
            return x.getName();
        }

        public void setName(String name) {
            x.setName(name);
        }

        @Param(name = "IP", type = ParamType.IP)
        public String getIP() {
            return x.getIp();
        }

        public void setIP(String ip) {
            x.setIp(ip);
        }

        @Action(name = Dialog.OK_ACTION)
        public void handleOK() {
            syncFromView();
            getPage().disposeView();
        }

        @Action(name = Dialog.CANCEL_ACTION)
        public void handleCANCEL() {
            x = null;
            getPage().disposeView();
        }

        public PLC getPLC() {
            return x;
        }
    }

    @PageDef(name = "Create/Modify Valve", icon = "valve64", layout = FormLayout.class)
    public static class ValveCreatorModifier extends Model {

        Valve x;
        List<PLC> plcs;
        Range port;

        public ValveCreatorModifier() {
            x = new Valve();
            plcs = DatabaseUnit.UNIT.selectAllPLCs();
            port = new Range(1, 4, 1);
        }

        public ValveCreatorModifier(Valve x) {
            this.x = x;
            plcs = DatabaseUnit.UNIT.selectAllPLCs();
            port = new Range(1, 4, x.getPortNum());
        }

        @Param(name = "Name", type = ParamType.STRING)
        public String getName() {
            return x.getName();
        }

        public void setName(String name) {
            x.setName(name);
        }

        @Param(name = "Port", type = ParamType.NUMMERIC_RANGE)
        public Range getPort() {
            return port;
        }

        @Param(name = "PLC", type = ParamType.OPTIONS)
        public List getPLCs() {
            return plcs;
        }

        @Action(name = Dialog.OK_ACTION)
        public void handleOK() {
            syncFromView();
            x.setPlcIp(((PLC) getPage().getParam("PLC").getSelectedItem()).getIp());
            x.setPortNum((short) port.getValue());
            getPage().disposeView();
        }

        @Action(name = Dialog.CANCEL_ACTION)
        public void handleCANCEL() {
            x = null;
            getPage().disposeView();
        }

        public Valve getValve() {
            return x;
        }
    }

    @PageDef(name = "Create/Modify Counter", icon = "water-counter64", layout = FormLayout.class)
    public static class CounterCreatorModifier extends Model {

        Counter x;
        List<PLC> plcs;
        Range port;
        Range resolution;

        public CounterCreatorModifier() {
            x = new Counter();
            plcs = DatabaseUnit.UNIT.selectAllPLCs();
            port = new Range(1, 4, 1);
            resolution = new Range(0.001, 100000, 1);
            resolution.setStepSize(0.001);
        }

        private CounterCreatorModifier(Counter c) {
            x = c;
            plcs = DatabaseUnit.UNIT.selectAllPLCs();
            port = new Range(1, 4, c.getPort());
            resolution = new Range(0.001, 100000, c.getPulseResolution());
        }

        @Param(name = "Name", type = ParamType.STRING, num=1)
        public String getName() {
            return x.getName();
        }

        public void setName(String name) {
            x.setName(name);
        }

        @Param(name = "Port", type = ParamType.NUMMERIC_RANGE, num=2)
        public Range getPort() {
            return port;
        }

        @Param(name="Pulse Resolution", type= ParamType.NUMMERIC_RANGE, num=3)
        public Range getResolution() {
            return resolution;
        }
        
        @Param(name = "PLC", type = ParamType.OPTIONS, num=0)
        public List getPLCs() {
            return plcs;
        }
        

        @Action(name = Dialog.OK_ACTION)
        public void handleOK() {
            syncFromView();
            x.setPlcIP(((PLC) getPage().getParam("PLC").getSelectedItem()).getIp());
            x.setPort((short) port.getValue());
            x.setPulseResolution(resolution.getValue());
            getPage().disposeView();
        }

        @Action(name = Dialog.CANCEL_ACTION)
        public void handleCANCEL() {
            x = null;
            getPage().disposeView();
        }

        public Counter getCounter() {
            return x;
        }
    }
}
